<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
	<head>
		<title>JavaScript Constructor Lab2</title>
		<style type="text/css">
			div#header {
				color: #0066FF;
				font-size: 25pt;
			}
			
			div#content {
				color: #B088FF;
				font-size: 12pt;
			}
		</style>
		<!-- embed jquery by google，藉由google嵌入jquery 1.4.4 -->
		<script type="text/javascript" src="http://www.google.com/jsapi"></script>
		<script type="text/javascript" language="javascript">
			google.load( "jquery", "1.4.4" );
		</script>
		<script type="text/javascript">
			$( document ).ready( function() {
				
				// 建構子函式
				var Employee = function( empId, empName, empAge ) {
					this.empId = empId;
					this.empName = empName;
					this.empAge = empAge;
					
					// 以下應用了javascript的closure特性，來保護私有變數，模擬OO的私有成員
					this.getEmpId = function() {
						return this.empId;
					};
					this.getEmpName = function() {
						return this.empName;
					};
					this.getEmpAge = function() {
						return this.empAge;
					};
					
					
					// 第一種解法，把目標物件當作引數傳入內嵌函式
					this.toString = function( target ) {
						alert(
							"target name is " + target.getEmpName() + "\n" + 
							"target id is " + target.getEmpId() + "\n" + 
							"target age is " + target.getEmpAge()
						);
						return {
							// 注意，在此必須確實使用()呼叫函式，因為要取得的是函式的回傳值，而不是註冊函式
							name: target.getEmpName(),
							id: target.getEmpId(),
							age: target.getEmpAge()
						};
					};
					
					// 第二種解法，利用Free Variable與Closure: 把在外部函式的this參照傳入內嵌函式中
					var innerThis = this;
					this.showDetail = function() {
						alert(
							"innerThis name is " + innerThis.getEmpName() + "\n" + 
							"innerThis id is " + innerThis.getEmpId() + "\n" + 
							"innerThis age is " + innerThis.getEmpAge()
						);
						return {
							name: innerThis.getEmpName(),
							id: innerThis.getEmpId(),
							age: innerThis.getEmpAge()
						};
					};
					
				};
				
				var e = new Employee( "000214", "Pony", 25 );
				var result = e.toString( e );
				
				// ok!
				alert(
					"name is " + result.name + "\n" + 
					"id is " + result.id + "\n" + 
					"age is " + result.age
				);
				
				// ok!
				alert(
					"emp name is " + e.getEmpName() + "\n" + 
					"emp id is " + e.getEmpId() + "\n" + 
					"emp name age " + e.getEmpAge()
				);
				
				// ok!
				var details = e.showDetail();
				alert(
					"details name is " + details.name + "\n" + 
					"details id is " + details.id + "\n" + 
					"details age is " + details.age
				);
				
				// 印出undefined! 因為在Employee函式中使用了closure保護了私有成員，無法直接存取
				alert(
					"e.name is " + e.name + "\n" + 
					"e.id is " + e.id + "\n" + 
					"e.age is " + e.age
				);
				
				/**************************************************************************/
				
				// 建構子函式
				var Account = function( accountId, owner ) {
					this.balance = 0;
					this.accountId = accountId;
					this.owner = owner;
					var innerThis = this;
					
					this.getBalance = function() {
						return this.balance;
					};
					this.setBalance = function( money ) {
						if( money < 0 ) {
							throw new Error( "money can't not lower than 0..." );
						}
						this.balance += money;
					};
					this.getOwner = function() {
						return this.owner;
					};
					this.getAccountId = function() {
						return this.accountId;
					};
					this.getDetail = function() {
						return {
							id: innerThis.getAccountId(),
							owner: innerThis.getOwner(),
							balance: innerThis.getBalance()
						};
					};
				};
				
				var account = new Account( "1234", "Jaco Pastorius" );
				account.setBalance( 5000 );
				var detail = account.getDetail();
				alert(
					"The owner is " + detail.owner + "\n" + 
					"The id is " + detail.id + "\n" + 
					"The balance is " + detail.balance
				);
				
				/******************************************************
				參考:  
						http://caterpillar.onlyfun.net/Gossip/JavaScript/Constructor.html
						http://caterpillar.onlyfun.net/Gossip/JavaScript/Closure.html
				********************************************************/
				
			});
		</script>
		
	</head>
	
	<body>
		<div title="temp1" id="header">Hello HTML</div>
		<div title="temp1" id="content">Here is content</div>
	</body>
</html>